#pragma once

#include <QString>
#include <functional>
#include <vector>
#include <optional>
#include <memory>

// 前向声明
namespace infrastructure {
    struct ValidationResult;
}

namespace kernel {

// 前向声明，用于获取配置节
class IConfigurationSection;

/**
 * @brief 配置变更时的回调函数类型
 * @param key 变更的配置键
 * @param newValue 新的值
 */
using ConfigurationChangeCallback = std::function<void(const QString& key, const QString& newValue)>;

/**
 * @brief 订阅句柄，用于取消订阅
 */
using SubscriptionHandle = unsigned long;

/**
 * @class IConfiguration
 * @brief 为整个应用程序提供统一配置访问的接口。
 * 支持分层、热重载和类型化数据访问。
 */
class IConfiguration {
public:
    virtual ~IConfiguration() = default;

    // === 基本值获取 ===
    // 支持使用 "section:subsection:key" 的方式访问层级数据

    /**
     * @brief 获取一个字符串配置值
     * @param key 配置键
     * @param defaultValue 如果找不到键，则返回此默认值
     * @return QString 配置值
     */
    virtual QString getString(const QString& key, const QString& defaultValue = "") const = 0;

    /**
     * @brief 获取一个整数配置值
     */
    virtual int getInt(const QString& key, int defaultValue = 0) const = 0;

    /**
     * @brief 获取一个布尔配置值
     */
    virtual bool getBool(const QString& key, bool defaultValue = false) const = 0;

    /**
     * @brief 获取一个浮点数配置值
     */
    virtual double getDouble(const QString& key, double defaultValue = 0.0) const = 0;

    // === 基本值设置 ===

    /**
     * @brief 设置一个字符串配置值
     * @param key 配置键
     * @param value 配置值
     * @return bool 设置是否成功
     */
    virtual bool setString(const QString& key, const QString& value) = 0;

    /**
     * @brief 设置一个整数配置值
     * @param key 配置键
     * @param value 配置值
     * @return bool 设置是否成功
     */
    virtual bool setInt(const QString& key, int value) = 0;

    /**
     * @brief 设置一个布尔配置值
     * @param key 配置键
     * @param value 配置值
     * @return bool 设置是否成功
     */
    virtual bool setBool(const QString& key, bool value) = 0;

    /**
     * @brief 设置一个浮点数配置值
     * @param key 配置键
     * @param value 配置值
     * @return bool 设置是否成功
     */
    virtual bool setDouble(const QString& key, double value) = 0;

    /**
     * @brief 删除一个配置值
     * @param key 配置键
     * @return bool 删除是否成功
     */
    virtual bool removeKey(const QString& key) = 0;

    /**
     * @brief 保存配置到持久化存储
     * @return bool 保存是否成功
     */
    virtual bool save() = 0;

    // === 热重载与订阅 (Observer Pattern) ===

    /**
     * @brief 订阅一个配置键的变更通知
     * @param key 要监视的配置键
     * @param callback 当值变更时调用的回调函数
     * @return SubscriptionHandle 一个用于取消订阅的句柄
     */
    virtual SubscriptionHandle subscribe(const QString& key, ConfigurationChangeCallback callback) = 0;

    /**
     * @brief 取消对配置变更的订阅
     * @param handle 通过subscribe方法获取的句柄
     */
    virtual void unsubscribe(SubscriptionHandle handle) = 0;

    // === 配置验证 ===

    /**
     * @brief 检查加载的配置是否通过了所有验证规则
     * @return bool 如果配置有效则返回true
     */
    virtual bool isValid() const = 0;
    
    /**
     * @brief 获取配置验证结果
     * @return ValidationResult 详细的验证结果
     */
    virtual infrastructure::ValidationResult getValidationResult() const = 0;

    // === 高级功能：获取配置节 ===

    /**
     * @brief 获取一个配置的子节，方便对一组相关配置进行操作
     * @param key 配置节的键
     * @return std::optional<std::shared_ptr<IConfigurationSection>> 配置节的接口指针
     */
    virtual std::optional<std::shared_ptr<IConfigurationSection>> getSection(const QString& key) const = 0;

    // === 配置导入导出 ===

    /**
     * @brief 导出配置到文件
     * @param filePath 文件路径
     * @return bool 导出是否成功
     */
    virtual bool exportToFile(const QString& filePath) const = 0;

    /**
     * @brief 从文件导入配置
     * @param filePath 文件路径
     * @return bool 导入是否成功
     */
    virtual bool importFromFile(const QString& filePath) = 0;

    /**
     * @brief 导出配置为JSON字符串
     * @return QString JSON字符串
     */
    virtual QString exportToJson() const = 0;

    /**
     * @brief 从JSON字符串导入配置
     * @param jsonString JSON字符串
     * @return bool 导入是否成功
     */
    virtual bool importFromJson(const QString& jsonString) = 0;
};


/**
 * @class IConfigurationSection
 * @brief 代表IConfiguration的一个子部分
 */
class IConfigurationSection : public IConfiguration {
public:
    // 除了IConfiguration的所有功能外，还提供了获取自身路径和值的功能
    
    /**
     * @brief 获取当前配置节的路径
     * @return QString 路径
     */
    virtual QString getPath() const = 0;
    
    /**
     * @brief 获取当前配置节自身的值 (如果它是一个键值对)
     * @return std::optional<QString> 值
     */
    virtual std::optional<QString> getValue() const = 0;
};

} // namespace kernel